#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QTimer>
#include <QAbstractSocket>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    , udpSocket(new QUdpSocket(this))  // 初始化UDP套接字
    , senderPort(0)                    // 初始化端口
{
    ui->setupUi(this);
    ui->g_Ip_Edit->setText("192.168.31.255");
    ui->g_port_Edit->setText("9999");
    UPsocket = new QTcpSocket(this);//创建实例化对象
    client = new QTcpSocket(this);//创建实例化对象

    // 绑定UDP端口
    if (!udpSocket->bind(9999, QUdpSocket::ShareAddress)) {
        qDebug() << "UDP绑定失败：" << udpSocket->errorString();
    } else {
        qDebug() << "UDP已绑定，等待数据...";
    }

    // 获取底层套接字描述符
    int socketDescriptor = udpSocket->socketDescriptor();
    if (socketDescriptor == -1) {
        qDebug() << "获取套接字描述符失败：" << udpSocket->errorString();
    }

    // 使用系统API设置广播选项
    int broadcast = 1;
    if (setsockopt(socketDescriptor, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast)) == -1)
    {
        qDebug() << "无法开启广播权限：" << strerror(errno);
    }else{
        qDebug() << "成功开启广播";
    }

    // 连接接收信号
    connect(udpSocket, &QUdpSocket::readyRead, this, &Widget::onReadyRead); //UDP
    QObject::connect(client,SIGNAL(readyRead()),this,SLOT(readTcpSlot())); //TCP

}

Widget::~Widget()
{
    delete ui;
}

// 计算文件MD5值
QString calculateFileMD5(const QString &filePath) {
    QFile file(filePath);
    // 以只读方式打开文件
    if (!file.open(QIODevice::ReadOnly))
    {
        return ""; // 打开失败返回空字符串
    }
    QCryptographicHash hash(QCryptographicHash::Md5);
    // 向哈希对象添加文件数据
    if (hash.addData(&file))
    {
        return hash.result().toHex();// 计算并返回十六进制格式的MD5值
    }
    return ""; // 计算失败返回空字符串
}

//-----------------------点击搜索按键，设备搜索这块，即发送问询协议，通过协议搜索设备-------------------
void Widget::on_find_btn_clicked()
{
    // 序列化广播内容
    // 构建 Json 对象
    QJsonObject json;
    json.insert("request", "connect_info");
    json.insert("type", 0);
    // 构建 Json 文档
    QJsonDocument document;
    document.setObject(json);
    QByteArray sendData = document.toJson(QJsonDocument::Compact);
    // 广播地址和端口:尽量从UI界面的独有位置进行获取
    QHostAddress broadcastAddr("192.168.31.255");
    quint16 port = 9999;
    // 发送广播包
    qint64 bytesSent = udpSocket->writeDatagram(sendData, broadcastAddr, port);
    if (bytesSent == -1) {
        qDebug() << "广播消息发送失败：" << udpSocket->errorString();
    } else {
        qDebug() << "已发送广播消息：" << sendData;
    }
}

// 处理接收到的UDP数据
void Widget::onReadyRead()
{
    while (udpSocket->hasPendingDatagrams()) {
        QByteArray datagram;
        // 调整缓冲区大小
        datagram.resize(udpSocket->pendingDatagramSize());
        // 读取数据
        qint64 bytesRead = udpSocket->readDatagram(datagram.data(),datagram.size(), &senderAddr, &senderPort);
        if (bytesRead == -1)
        {
            qDebug() << "接收失败：" << udpSocket->errorString();
            continue;
        }
        QJsonParseError parseError;
        QJsonDocument jsonUDP = QJsonDocument::fromJson(datagram, &parseError);
        if (parseError.error != QJsonParseError::NoError)
        {
            qDebug() << "UDP JSON解析失败：" << parseError.errorString()<< "，错误位置：" << parseError.offset;
            continue; // 解析失败直接跳过
        }
        QJsonObject rootUDP = jsonUDP.object();
        QJsonObject dataUDP = rootUDP["data"].toObject();
        QString updateUDP = dataUDP["ver_address"].toString();
        QString verUDP = dataUDP["version"].toString();

        ui->Ip_Edit->setText(updateUDP);
        ui->ben_Edit->setText(verUDP);
    }
}

//连接TCP，当点击连接按钮启动
void Widget::on_connect_btn_clicked()
{
    client->connectToHost(QHostAddress("192.168.31.236"),8000);
    if(client->waitForConnected(3000))
    {
        qDebug() << "已经建立TCP连接";
    }
}
//--------------------获取文件信息--------------------------
void Widget::filerInfoFlog()
{
    //创建文件信息类的对象
    QFileInfo filer(readPath);
    //判断是否存在
    if(!filer.exists())
    {
        QMessageBox::warning(this,"提示","文件不存在");
        return;
    }
    //存在则获取文件大小、名称、是否可读
    qint64 filersize =filer.size();
    QString stext =QString ::number(filersize);
    QString size =QString ::number(filersize);
    stext.prepend("文件大小：").append("字节");
    ui->textBrowser->append(stext);
    QString text = filer.baseName().append(".zip");

    bool ret = filer.isReadable();
    if(ret == true)
    {
        ui->textBrowser->append("文件可读");
    }
    else
    {
        ui->textBrowser->append("文件不可读");
    }
    QString md5 = calculateFileMD5(readPath);
    QString size_md5 = calculateFileMD5(readPath);
    md5.prepend("文件MD5值：");
    ui->textBrowser->append(md5);
    //JSON格式
    // 构建 Json 对象
    QJsonObject json;
    QJsonObject data;
    data.insert("ver", "v2.0");
    data.insert("file_name", text);
    data.insert("file_len", size);
    data.insert("md5", size_md5);
    json.insert("type", 1);
    json.insert("data", data);
    // 构建 Json 文档
    QJsonDocument document;
    document.setObject(json);
    QByteArray sendup = document.toJson(QJsonDocument::Compact);
    // 发送升级包信息
    qint64 bytesSent =client->write(sendup);
    if (bytesSent == -1) {
        qDebug() << "升级包发送失败：" << client->errorString();
    } else {
        qDebug() << "已发送升级包信息：" << sendup;
    }
}

//发送升级包信息
void Widget::on_pushButton_clicked()
{
    //升级包的信息
    QString filer="所有文件(*.*);;Qt文件(*.cpp *.pro *.ui *.h)";
    QString path=QFileDialog::getOpenFileName(this,"打开","D:/",filer);

    if(path !="")
    {
            ui->textBrowser->append(path);//append:追加的意思
            readPath=path;
            filerInfoFlog();  //发送升级包消息
    }
     else if(readPath =="")
    {
        QMessageBox::warning(this,"提示","请选择你要打开的文件");
    }

}
void Widget::readTcpSlot()
{
    // 检查 client 是否有效
    if (!client) {
        qDebug() << "TCP客户端未初始化";
        return;
    }

    // 读取所有可用数据，追加到缓冲区
    tcpBuffer += client->readAll();
    qDebug() << "当前缓冲区数据:" << tcpBuffer;

    // 循环处理缓冲区中的完整JSON对象
    while (!tcpBuffer.isEmpty()) {
        // 查找JSON对象的边界（简化处理，实际可根据需要完善）
        int startIndex = tcpBuffer.indexOf('{');
        if (startIndex == -1) {
            // 没有找到起始符，清空无效数据
            tcpBuffer.clear();
            break;
        }

        // 从起始位置开始查找匹配的结束符
        int balance = 0;
        int endIndex = -1;
        for (int i = startIndex; i < tcpBuffer.size(); ++i) {
            if (tcpBuffer[i] == '{') {
                balance++;
            } else if (tcpBuffer[i] == '}') {
                balance--;
                if (balance == 0) {
                    endIndex = i;
                    break;
                }
            }
        }

        if (endIndex == -1) {
            // 没有找到完整的结束符，保留缓冲区等待后续数据
            tcpBuffer = tcpBuffer.mid(startIndex);
            break;
        }

        // 提取完整的JSON片段
        QByteArray jsonData = tcpBuffer.mid(startIndex, endIndex - startIndex + 1);
        // 更新缓冲区，保留剩余数据
        tcpBuffer = tcpBuffer.mid(endIndex + 1);

        qDebug() << "提取到完整JSON:" << jsonData;

        // 解析JSON数据
        QJsonParseError jsonError;
        QJsonDocument doc = QJsonDocument::fromJson(jsonData, &jsonError);

        if (jsonError.error != QJsonParseError::NoError) {
            qDebug() << "JSON解析错误：" << jsonError.errorString()
                     << "，错误位置：" << jsonError.offset;
            continue;
        }

        if (!doc.isObject()) {
            qDebug() << "JSON格式错误：不是有效的JSON对象";
            continue;
        }

        QJsonObject rootObj = doc.object();

        if (!rootObj.contains("type")) {
            qDebug() << "JSON数据缺少type字段";
            continue;
        }

        int type = rootObj["type"].toInt();

        // 处理不同类型的消息（保持原有逻辑）
        switch (type) {
            case 1: {
                if (rootObj.contains("data") && rootObj["data"].isObject()) {
                    QJsonObject dataObj = rootObj["data"].toObject();
                    QString updateStr = dataObj["update"].toString();
                    qDebug() << "update值:" << updateStr;

                    if (updateStr == "false") {
                        QMessageBox::warning(this, "提示", "设备版本已经是最新版本");
                    } else {
                        QMessageBox::warning(this, "提示", "请对设备进行升级");
                    }
                } else {
                    qDebug() << "type=1的消息缺少有效的data对象";
                }
                break;
            }

            case 2: {
                if (rootObj.contains("data") && rootObj["data"].isObject()) {
                    QJsonObject dataObj = rootObj["data"].toObject();
                    QString transSuccess = dataObj["trans_success"].toString();
                    qDebug() << "trans_success值:" << transSuccess;
                } else {
                    qDebug() << "type=2的消息缺少有效的data对象";
                }
                break;
            }

            case 3: {
                if (rootObj.contains("data") && rootObj["data"].isObject()) {
                    QJsonObject dataObj = rootObj["data"].toObject();
                    QString updateSuccess = dataObj["update_success"].toString();
                    qDebug() << "update_success值:" << updateSuccess;

                    QMessageBox::information(this, "完成", "升级成功");
                    ui->textBrowser->append("设备升级成功");
                } else {
                    qDebug() << "type=3的消息缺少有效的data对象";
                }
                break;
            }

            case 5: {
                if (rootObj.contains("data") && rootObj["data"].isObject()) {
                    QJsonObject dataObj = rootObj["data"].toObject();
                    int progress = dataObj["progress"].toInt();
                    qDebug() << "解析到progress：" << progress;
                    ui->progressBar->setValue(progress);
                } else {
                    qDebug() << "type=5的消息缺少有效的data对象";
                }
                break;
            }
            default:
                qDebug() << "收到未知类型的消息，type=" << type;
                break;
        }
    }
}

//传输文件
void Widget::on_update_btn_clicked()
{
    // 连接到Linux服务器的8001端口
    UPsocket->connectToHost(QHostAddress("192.168.31.236"),8001);
    if(UPsocket->waitForConnected(3000))
    {
        qDebug() << "已经建立UP_TCP连接";
    }
    //文件发送成功
        QFile file(readPath);
           if (!file.open(QIODevice::ReadOnly)) {
               QMessageBox::critical(this, "错误", "无法打开文件");
               UPsocket->close();
               return;
           }
           qint64 fileSize = file.size();
           qint64 totalSent = 0;
           const qint64 blockSize = 4096;
           //ui->progressBar->setValue(0);
           while (!file.atEnd()) {
               if (UPsocket->state() != QAbstractSocket::ConnectedState) {
                   QMessageBox::critical(this, "错误", "连接已断开");
                   file.close();
                   UPsocket->close();
                   return;
               }

               QByteArray block = file.read(blockSize);
               qint64 sent = UPsocket->write(block);
               if (sent == -1) {
                   QMessageBox::critical(this, "错误", "发送失败");
                   file.close();
                   UPsocket->close();
                   return;
               }

               totalSent += sent;
               //ui->progressBar->setValue((totalSent * 100) / fileSize);
               UPsocket->waitForBytesWritten(50);
           }

           // 完成处理
           file.close();
           UPsocket->close();
           //ui->progressBar->setValue(100);
}

